home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / link.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  16KB  |  540 lines

  1. {
  2.     $Id: link.pas,v 1.2.2.4 1998/08/31 12:19:29 peter Exp $
  3.     Copyright (c) 1998 by the FPC development team
  4.  
  5.     This unit handles the linker and binder calls for programs and
  6.     libraries
  7.  
  8.     This program is free software; you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation; either version 2 of the License, or
  11.     (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; if not, write to the Free Software
  20.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.  ****************************************************************************
  23. }
  24. Unit link;
  25.  
  26. Interface
  27.  
  28. uses cobjects;
  29.  
  30. Type TLinker = Object
  31.      { Internal variables. Don't access directly }
  32.        {$ifdef linux}
  33.        LinkToC : Boolean;                 { Should we link to the C libs? }
  34.        GccLibraryPath : String;           { Where is GCCLIB ? }
  35.        DynamicLinker : String;            { What Dynamic linker ? }
  36.        {$endif}
  37.        OFiles, LibFiles : TStringContainer;
  38.        Strip : Boolean;                   { Strip symbols ? }
  39.        MakeLib : Boolean;                 { If unit : Make library ?}
  40.        ExeName,                           { FileName of the exe to be created }
  41.        LibName     : String;              { FileName of the lib to be created }
  42.        LinkResName : String[32];          { Name of response file }
  43.        LinkOptions : String;              { Additional options to the linker }
  44.        LibrarySearchPath : String;        { Where to look for libraries }
  45.      { Methods }
  46.        Constructor Init;
  47.        Procedure SetFileName(const s:string);
  48.        function  FindObjectFile(s : string) : string;
  49.        Procedure AddLibraryFile(S : String);
  50.        Procedure AddObjectFile(S : String);
  51.        Function  FindLinker : String;      { Find linker, sets Name }
  52.        Function  DoExec(const command,para:string):boolean;
  53.        Function  WriteResponseFile : Boolean;
  54.        Function  Link:boolean;
  55.        Procedure Make_Library;
  56.      end;
  57.      PLinker=^TLinker;
  58.  
  59. Var Linker : TLinker;
  60.  
  61.  
  62. Implementation
  63.  
  64. uses
  65.   Script,globals,systems,dos,verbose;
  66.  
  67. Constructor TLinker.Init;
  68. begin
  69.   OFiles.Init;
  70.   LibFiles.Init;
  71.   OFiles.Doubles:=False;
  72.   LibFiles.Doubles:=False;
  73.   Strip:=false;
  74.   LinkOptions:='';
  75.   LinkResName:='link.res';
  76.   ExeName:='';
  77.   LibName:='';
  78. {$ifdef linux}
  79.   LinkToC:=False;
  80.   LibrarySearchPath:='';
  81.   DynamicLinker:='/lib/ld-linux.so.1';
  82. {$endif}
  83. end;
  84.  
  85.  
  86. Procedure TLinker.SetFileName(const s:string);
  87. var
  88.   path:dirstr;
  89.   name:namestr;
  90.   ext:extstr;
  91. begin
  92.   FSplit(s,path,name,ext);
  93.   LibName:=Path+Name+target_info.DllExt;
  94.   ExeName:=Path+Name+target_info.ExeExt;
  95. end;
  96.  
  97.  
  98. var
  99.   LastLDBin : string;
  100. Function TLinker.FindLinker:string;
  101. var
  102.   ldfound : boolean;
  103. begin
  104.   if LastLDBin='' then
  105.    begin
  106.      if (target_info.target=target_WIN32) then
  107.      { the win32 linker has another name to allow cross compiling between }
  108.      { DOS and Win32, I think it should be possible to compile an ld      }
  109.      { with handles coff and pe, but I don't know how      (FK)           }
  110.        LastLDBin:=FindExe('ldw',ldfound)
  111.      else
  112.        LastLDBin:=FindExe('amigald',ldfound);
  113.      if (not ldfound) and (not externlink) then
  114.       begin
  115.         Message1(exec_w_linker_not_found,LastLDBin);
  116.         externlink:=true;
  117.       end;
  118.      if ldfound then
  119.       Message1(exec_u_using_linker,LastLDBin);
  120.    end;
  121.   FindLinker:=LastLDBin;
  122. end;
  123.  
  124.  
  125. { searches an object file }
  126. function TLinker.FindObjectFile(s:string) : string;
  127. var
  128.   found : boolean;
  129. begin
  130.   if pos('.',s)=0 then
  131.    s:=s+target_info.objext;
  132.   s:=FixFileName(s);
  133.   if FileExists(s) then
  134.    begin
  135.      Findobjectfile:=s;
  136.      exit;
  137.    end;
  138.   findobjectfile:=search(s,'.;'+unitsearchpath+';'+exepath,found)+s;
  139.   if (not externasm) and (not found) then
  140.    Message1(exec_e_objfile_not_found,s);
  141. end;
  142.  
  143.  
  144. Procedure TLInker.AddObjectFile (S : String);
  145. begin
  146.   if pos('.',s)=0 then
  147.    s:=s+target_info.objext;
  148.   s:=FixFileName(s);
  149.   OFiles.Insert (S);
  150. end;
  151.  
  152.  
  153. Procedure TLInker.AddLibraryFile(S:String);
  154. begin
  155.   if pos('.',s)=0 then
  156.    s:=s+target_info.dllext;
  157.   LibFiles.Insert (S);
  158. end;
  159.  
  160.  
  161. Function TLinker.DoExec(const command,para:string):boolean;
  162. begin
  163.   DoExec:=true;
  164.   if not externlink then
  165.    begin
  166.      swapvectors;
  167.      exec(command,para);
  168.      swapvectors;
  169.      if (dosexitcode<>0) then
  170.       begin
  171.         Message(exec_w_error_while_linking);
  172.         DoExec:=false;
  173.         exit;
  174.       end
  175.      else
  176.       if (dosError<>0) then
  177.        begin
  178.          Message(exec_w_cant_call_linker);
  179.          ExternLink:=true;
  180.        end;
  181.    end;
  182.   if externlink then
  183.    AsmRes.AddLinkCommand (Command,Para,ExeName);
  184. end;
  185.  
  186.  
  187. Function TLinker.WriteResponseFile : Boolean;
  188. Var
  189.   LinkResponse : Text;
  190.   i            : longint;
  191.   prtobj,s     : string;
  192. begin
  193. { Open linkresponse and write header }
  194.   assign(linkresponse,inputdir+LinkResName);
  195.   rewrite(linkresponse);
  196.  
  197. { Write Header and set runtime object (prt0) }
  198.   case target_info.target of
  199.    target_WIN32 : begin
  200.                     prtobj:='';
  201.                     writeln(linkresponse,'INPUT (');
  202.                   end;
  203.    target_PalmOS:
  204.      begin
  205.         prtobj:='';
  206.      end;
  207.    target_linux : begin
  208.                     if cs_profile in aktswitches then
  209.                      prtobj:='gprt0'
  210.                     else
  211.                      prtobj:='prt0';
  212. {$ifdef Linux}
  213.                     if LinkToC then
  214.                      writeln(linkresponse,'SEARCH_DIR ('+GCCLibraryPath +')');
  215. {$endif}
  216.                     writeln(linkresponse,'INPUT (');
  217.                   end;
  218.    target_AMIGA: begin
  219.                      prtobj:='prt0';
  220.                      writeln(linkresponse,'INPUT (');
  221.                  end;
  222.   else
  223.    prtobj:='prt0';
  224.   end;
  225.  
  226. { add objectfiles, start with prt0 always }
  227.   if prtobj<>'' then
  228.    Writeln(linkresponse,FindObjectFile(prtobj));
  229.   while not OFiles.Empty do
  230.    begin
  231.      s:=Findobjectfile(OFiles.Get);
  232.      if s<>'' then
  233.       Writeln(linkresponse,s);
  234.    end;
  235.  
  236. { Write libraries like -l<lib> }
  237.   While not LibFiles.Empty do
  238.    begin
  239.      S:=LibFiles.Get;
  240.      i:=Pos(target_info.dllext,S);
  241.      if i>0 then
  242.       Delete(S,i,255);
  243.      Writeln (LinkResponse,'-l'+S);
  244.    end;
  245.  
  246. { Write End of response file }
  247.   if target_info.target in [target_WIN32,target_linux,target_AMIGA] then
  248.     Writeln (LinkResponse,')');
  249.  
  250. { Close response }
  251.   close(linkresponse);
  252.   WriteResponseFile:=True;
  253. end;
  254.  
  255.  
  256. Function TLinker.link:boolean;
  257. var
  258.   bindbin    : string[80];
  259.   bindfound  : boolean;
  260.   _stacksize,i,
  261.   _heapsize  : longint;
  262.   s,s2       : string[10];
  263.   dummy      : file;
  264.   success    : boolean;
  265. begin
  266. {$ifdef linux}
  267.   if LinkToC then
  268.    begin
  269.      AddObjectFile('/usr/lib/crt0.o');
  270.      AddObjectFile(FindObjectFile('lprt'));
  271.      AddLibraryFile('libc.a');
  272.      AddLibraryFile('libgcc.a');
  273.    end;
  274. {$endif Linux}
  275.  
  276. { Create Linkoptions }
  277.   case target_info.target of
  278.      target_GO32V1:
  279.        LinkOptions:=LinkOptions+' -oformat coff-go32';
  280.      target_GO32V2:
  281.        LinkOptions:=LinkOptions+' -oformat coff-go32-exe';
  282.       target_linux: begin
  283.                       if cs_profile in aktswitches then
  284.                        begin
  285.                          AddLibraryFile('gmon');
  286.                          AddLibraryFile('c');
  287.                        end;     
  288.                     end;
  289.   end;
  290.  
  291. {$ifdef linux}
  292.   If not LibFiles.Empty then
  293.    LinkOptions:='-dynamic-linker='+DynamicLinker+' '+LinkOptions;
  294. {$endif linux}
  295.  
  296.   if Strip then
  297.    LinkOptions:=LinkOptions+' -s';
  298.  
  299. { Write used files and libraries }
  300.   WriteResponseFile;
  301.  
  302. { Call linker }
  303.   if not externlink then
  304.    Message1(exec_i_linking,ExeName);
  305. {$ifdef linux}
  306.   success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+LinkResName);
  307. {$else}
  308.   if target_info.target in [target_WIN32,target_AMIGA] then
  309.     success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+LinkResName)
  310.   else
  311.     success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' @'+inputdir+LinkResName);
  312. {$endif}
  313.  
  314. {Bind}
  315.   if target_info.target=target_os2 then
  316.    begin
  317.    {Calculate the stack and heap size in kilobytes, rounded upwards.}
  318.      _stacksize:=(stacksize+1023) shr 10;
  319.    {Minimum stacksize for EMX is 32K.}
  320.      if _stacksize<32 then
  321.       _stacksize:=32;
  322.      str(_stacksize,s);
  323.      _heapsize:=(heapsize+1023) shr 10;
  324.      str(_heapsize,s2);
  325.      bindbin:=FindExe('emxbind',bindfound);
  326.      if (not bindfound) and (not externlink) then
  327.       begin
  328.         Message(exec_w_binder_not_found);
  329.         externlink:=true;
  330.       end;
  331.      DoExec(bindbin,'-k'+s+' -o '+exename+'.exe '+exename+' -aim -s'+s2);
  332.    end;
  333.   if (success) and (not externlink) then
  334.    begin
  335.      assign(dummy,LinkResName);
  336.      {$I-}
  337.       erase(dummy);
  338.      {$I+}
  339.      i:=ioresult;
  340.    end;
  341.   link:=success;   { otherwise a recursive call to link method }
  342. end;
  343.  
  344.  
  345. Procedure TLinker.Make_Library;
  346. {$ifndef linux}
  347. var
  348.   arbin : string;
  349.   arfound : boolean;
  350. {$endif}
  351. begin
  352.   if cs_shared_lib in initswitches then
  353.    begin
  354.      WriteResponseFile;
  355. {$ifdef linux}
  356.      DoExec(FindLinker,' -o '+libname+'.so -shared link.res');
  357. {$else}
  358.      arbin:=FindExe('ar',arfound);
  359.      if (not arfound) and (not externlink) then
  360.       begin
  361.         Message(exec_w_ar_not_found);
  362.         externlink:=true;
  363.       end;
  364.      DoExec(arbin,'rs '+libname+'.a');
  365. {$endif}
  366.    end;
  367. end;
  368.  
  369. end.
  370. {
  371.   $Log: link.pas,v $
  372.   Revision 1.2.2.4  1998/08/31 12:19:29  peter
  373.     * linux fixes
  374.  
  375.   Revision 1.2.2.3  1998/08/18 13:44:49  carl
  376.     * Amiga LD was not called correctly
  377.  
  378.   Revision 1.2.2.2  1998/08/13 17:41:23  florian
  379.     + some stuff for the PalmOS added
  380.  
  381.   Revision 1.2.2.1  1998/08/13 13:22:34  carl
  382.     + Amiga target ld script
  383.  
  384.   Revision 1.2  1998/03/30 09:50:49  michael
  385.   + fix for library support.
  386.  
  387.   Revision 1.1.1.1  1998/03/25 11:18:13  root
  388.   * Restored version
  389.  
  390.   Revision 1.31  1998/03/13 22:45:58  florian
  391.     * small bug fixes applied
  392.  
  393.   Revision 1.30  1998/03/11 22:22:52  florian
  394.     * Fixed circular unit uses, when the units are not in the current dir (from Peter)
  395.     * -i shows correct info, not <lf> anymore (from Peter)
  396.     * linking with shared libs works again (from Peter)
  397.  
  398.   Revision 1.29  1998/03/10 16:27:39  pierre
  399.     * better line info in stabs debug
  400.     * symtabletype and lexlevel separated into two fields of tsymtable
  401.     + ifdef MAKELIB for direct library output, not complete
  402.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  403.       working
  404.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  405.       working
  406.  
  407.   Revision 1.28  1998/03/10 01:17:19  peter
  408.     * all files have the same header
  409.     * messages are fully implemented, EXTDEBUG uses Comment()
  410.     + AG... files for the Assembler generation
  411.  
  412.   Revision 1.27  1998/03/05 22:43:47  florian
  413.     * some win32 support stuff added
  414.  
  415.   Revision 1.26  1998/03/04 01:35:04  peter
  416.     * messages for unit-handling and assembler/linker
  417.     * the compiler compiles without -dGDB, but doesn't work yet
  418.     + -vh for Hint
  419.  
  420.   Revision 1.25  1998/03/02 01:48:42  peter
  421.     * renamed target_DOS to target_GO32V1
  422.     + new verbose system, merged old errors and verbose units into one new
  423.       verbose.pas, so errors.pas is obsolete
  424.  
  425.   Revision 1.24  1998/03/01 22:46:12  florian
  426.     + some win95 linking stuff
  427.     * a couple of bugs fixed:
  428.       bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
  429.  
  430.   Revision 1.23  1998/02/28 03:56:15  carl
  431.     + replaced target_info.short_name by target_info.target (a bit faster)
  432.  
  433.   Revision 1.22  1998/02/26 11:57:09  daniel
  434.   * New assembler optimizations commented out, because of bugs.
  435.   * Use of dir-/name- and extstr.
  436.  
  437.   Revision 1.21  1998/02/25 20:26:41  michael
  438.   + fixed linking for linux
  439.  
  440.   Revision 1.20  1998/02/24 14:20:53  peter
  441.     + tstringcontainer.empty
  442.     * ld -T option restored for linux
  443.     * libraries are placed before the objectfiles in a .PPU file
  444.     * removed 'uses link' from files.pas
  445.  
  446.   Revision 1.19  1998/02/23 02:54:23  carl
  447.     * bugfix of recusrive call to link
  448.  
  449.   Revision 1.18  1998/02/22 23:03:18  peter
  450.     * renamed msource->mainsource and name->unitname
  451.     * optimized filename handling, filename is not seperate anymore with
  452.       path+name+ext, this saves stackspace and a lot of fsplit()'s
  453.     * recompiling of some units in libraries fixed
  454.     * shared libraries are working again
  455.     + $LINKLIB <lib> to support automatic linking to libraries
  456.     + libraries are saved/read from the ppufile, also allows more libraries
  457.       per ppufile
  458.  
  459.   Revision 1.17  1998/02/19 00:11:00  peter
  460.     * fixed -g to work again
  461.     * fixed some typos with the scriptobject
  462.  
  463.   Revision 1.16  1998/02/18 13:48:16  michael
  464.   + Implemented an OS independent AsmRes object.
  465.  
  466.   Revision 1.15  1998/02/18 08:55:26  michael
  467.   * Removed double declaration of LinkerOptions
  468.  
  469.   Revision 1.14  1998/02/17 21:20:50  peter
  470.     + Script unit
  471.     + __EXIT is called again to exit a program
  472.     - target_info.link/assembler calls
  473.     * linking works again for dos
  474.     * optimized a few filehandling functions
  475.     * fixed stabs generation for procedures
  476.  
  477.   Revision 1.13  1998/02/16 13:46:40  michael
  478.   + Further integration of linker object:
  479.     - all options pertaining to linking go directly to linker object
  480.     - removed redundant variables/procedures, especially in OS_TARG...
  481.  
  482.   Revision 1.12  1998/02/16 12:51:31  michael
  483.   + Implemented linker object
  484.  
  485.   Revision 1.11  1998/02/15 21:16:21  peter
  486.     * all assembler outputs supported by assemblerobject
  487.     * cleanup with assembleroutputs, better .ascii generation
  488.     * help_constructor/destructor are now added to the externals
  489.     - generation of asmresponse is not outputformat depended
  490.  
  491.   Revision 1.10  1998/02/14 01:45:21  peter
  492.     * more fixes
  493.     - pmode target is removed
  494.     - search_as_ld is removed, this is done in the link.pas/assemble.pas
  495.     + findexe() to search for an executable (linker,assembler,binder)
  496.  
  497.   Revision 1.9  1998/02/13 22:26:28  peter
  498.     * fixed a few SigSegv's
  499.     * INIT$$ was not written for linux!
  500.     * assembling and linking works again for linux and dos
  501.     + assembler object, only attasmi3 supported yet
  502.     * restore pp.pas with AddPath etc.
  503.  
  504.   Revision 1.8  1998/02/13 10:35:09  daniel
  505.   * Made Motorola version compilable.
  506.   * Fixed optimizer
  507.  
  508. >>>>>>> h:/cvs/compiler/link.pas
  509.   Revision 1.7  1998/02/02 00:55:32  peter
  510.     * defdatei -> deffile and some german comments to english
  511.     * search() accepts : as seperater under linux
  512.     * search for ppc.cfg doesn't open a file (and let it open)
  513.     * reorganize the reading of parameters/file a bit
  514.     * all the PPC_ environments are now for all platforms
  515.  
  516.   Revision 1.6  1998/02/01 15:02:11  florian
  517.     * swapvectors around exec inserted
  518.  
  519.   Revision 1.5  1998/01/28 13:48:39  michael
  520.   + Initial implementation for making libs from within FPC. Not tested, as compiler does not run
  521.  
  522.   Revision 1.4  1998/01/25 18:45:43  peter
  523.     + Search for as and ld at startup
  524.     + source_info works the same as target_info
  525.     + externlink allows only external linking
  526.  
  527.   Revision 1.3  1998/01/24 00:36:07  florian
  528.     + small fix to get it working with DOS (dynamiclinker isn't declared for dos)
  529.  
  530.   Revision 1.2  1998/01/23 22:19:17  michael
  531.   + Implemented setting of dynamic linker name (linux only).
  532.     Declared Make_library
  533.     -Fd switch sets linker (linux only)
  534.   * Reinstated -E option of Pierre
  535.  
  536.   Revision 1.1  1998/01/23 17:57:41  michael
  537.   + Initial implementation.
  538.  
  539. }
  540.